package no.nordicsemi.android.toolbox.profile.manager.repository

import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.update
import no.nordicsemi.android.toolbox.profile.data.UARTRecord
import no.nordicsemi.android.toolbox.profile.data.UARTRecordType
import no.nordicsemi.android.toolbox.profile.data.UARTServiceData
import no.nordicsemi.android.toolbox.profile.data.uart.MacroEol
import no.nordicsemi.android.toolbox.profile.data.uart.UARTConfiguration
import no.nordicsemi.android.toolbox.profile.data.uart.UARTMacro
import no.nordicsemi.android.toolbox.profile.data.uart.parseWithNewLineChar
import no.nordicsemi.android.toolbox.profile.manager.UARTManager

object UartRepository {
    private val _dataMap = mutableMapOf<String, MutableStateFlow<UARTServiceData>>()

    fun getData(deviceId: String): Flow<UARTServiceData> {
        return _dataMap.getOrPut(deviceId) { MutableStateFlow(UARTServiceData()) }
    }

    fun updateMaxWriteLength(deviceId: String, maxWriteLength: Int) {
        _dataMap[deviceId]?.update {
            it.copy(maxWriteLength = maxWriteLength)
        }
    }

    fun onNewMessageReceived(deviceId: String, message: String, rawData: ByteArray? = null) {
        _dataMap[deviceId]?.update {
            // 解析传感器数据（如果是34字节的数据帧）
            val sensorData = if (rawData != null && rawData.size == 34) {
                parseSensorData(rawData)
            } else {
                it.sensorData  // 保持之前的传感器数据
            }
            
            it.copy(
                messages = it.messages + UARTRecord(message, UARTRecordType.OUTPUT, rawData = rawData),
                sensorData = sensorData
            )
        }
    }
    
    // 解析34字节的传感器数据帧
    // 格式：CC DD AB | AA B0 XX XX | AA B1 XX XX | ... | FF FF FF
    private fun parseSensorData(data: ByteArray): no.nordicsemi.android.toolbox.profile.data.UARTSensorData {
        return try {
            // 验证数据长度
            if (data.size != 34) {
                return no.nordicsemi.android.toolbox.profile.data.UARTSensorData(isValid = false)
            }
            
            // 验证帧头：CC DD AB
            if (data[0] != 0xCC.toByte() || data[1] != 0xDD.toByte() || data[2] != 0xAB.toByte()) {
                return no.nordicsemi.android.toolbox.profile.data.UARTSensorData(isValid = false)
            }
            
            // 验证帧尾：FF FF FF
            if (data[31] != 0xFF.toByte() || data[32] != 0xFF.toByte() || data[33] != 0xFF.toByte()) {
                return no.nordicsemi.android.toolbox.profile.data.UARTSensorData(isValid = false)
            }
            
            // 解析温度 (AA B0 XX XX) - 字节3-6
            val temperature = if (data[3] == 0xAA.toByte() && data[4] == 0xB0.toByte()) {
                parseUInt16(data, 5) / 100.0f  // 假设需要除以10，请根据实际调整
            } else 0f
            
            // 解析压力 (AA B1 XX XX) - 字节7-10
            val pressure = if (data[7] == 0xAA.toByte() && data[8] == 0xB1.toByte()) {
                parseUInt16(data, 9) / 100.0f  // 假设需要除以10，请根据实际调整
            } else 0f
            
            // 解析心率 (AA B2 XX XX) - 字节11-14
            val heartRate = if (data[11] == 0xAA.toByte() && data[12] == 0xB2.toByte()) {
                parseUInt16(data, 13)
            } else 0
            
            // 解析血氧 (AA B3 XX XX) - 字节15-18
            val bloodOxygen = if (data[15] == 0xAA.toByte() && data[16] == 0xB3.toByte()) {
                parseUInt16(data, 17)
            } else 0
            
            // 解析血容量 (AA B4 XX XX) - 字节19-22
            val bloodVolume = if (data[19] == 0xAA.toByte() && data[20] == 0xB4.toByte()) {
                parseUInt16(data, 21).toFloat()  // 根据实际数据调整（如果是整数1，不需要转换）
            } else 0f
            
            // 解析阻抗 (AA B5 XX XX) - 字节23-26
            val impedance = if (data[23] == 0xAA.toByte() && data[24] == 0xB5.toByte()) {
                parseUInt16(data, 25).toFloat()  // 根据实际数据调整（如果是整数1，不需要转换）
            } else 0f
            
            // 解析电量 (AA B6 XX XX) - 字节27-30
            val battery = if (data[27] == 0xAA.toByte() && data[28] == 0xB6.toByte()) {
                parseUInt16(data, 29)
            } else 0
            
            no.nordicsemi.android.toolbox.profile.data.UARTSensorData(
                temperature = temperature,
                pressure = pressure,
                heartRate = heartRate,
                bloodOxygen = bloodOxygen,
                bloodVolume = bloodVolume,
                impedance = impedance,
                battery = battery,
                isValid = true
            )
        } catch (e: Exception) {
            // 解析失败，返回默认值
            no.nordicsemi.android.toolbox.profile.data.UARTSensorData(isValid = false)
        }
    }
    
    // 解析2字节无符号整数（小端序 - Little Endian）
    private fun parseUInt16(data: ByteArray, offset: Int): Int {
        // 小端序：低字节在前，高字节在后（与 sys_put_le16 对应）
        return (data[offset].toInt() and 0xFF) or ((data[offset + 1].toInt() and 0xFF) shl 8)
    }

    private fun getMaxWriteLength(deviceId: String): Int {
        return _dataMap[deviceId]?.value?.maxWriteLength ?: 20
    }

    fun onNewMessageSent(deviceId: String, message: String) {
        _dataMap[deviceId]?.update {
            it.copy(messages = it.messages + UARTRecord(message, UARTRecordType.INPUT))
        }
    }

    suspend fun sendText(deviceId: String, text: String, newLineChar: MacroEol) {
        if (_dataMap.containsKey(deviceId)) {
            UARTManager.sendText(
                deviceId,
                text.parseWithNewLineChar(newLineChar),
                getMaxWriteLength(deviceId)
            )
        }
    }
    
    /**
     * 发送字节数组（用于二进制命令）
     */
    suspend fun sendBytes(deviceId: String, data: ByteArray) {
        if (_dataMap.containsKey(deviceId)) {
            UARTManager.sendBytes(
                deviceId,
                data,
                getMaxWriteLength(deviceId)
            )
        }
    }

    suspend fun runMacro(deviceId: String, macro: UARTMacro) {
        if (macro.command == null) return
        // Send the command to the device and update the command message.
        if (_dataMap.containsKey(deviceId)) {
            UARTManager.sendText(
                deviceId,
                macro.command!!.parseWithNewLineChar(macro.newLineChar),
                getMaxWriteLength(deviceId),
            )
        }
    }

    fun clear(deviceId: String) {
        _dataMap.remove(deviceId)
    }

    fun clearOutputItems(deviceId: String) {
        _dataMap[deviceId]?.update {
            it.copy(messages = emptyList())
        }
    }

    fun deleteConfiguration(deviceId: String, configuration: UARTConfiguration) {
        _dataMap[deviceId]?.update {
            it.copy(uartViewState = it.uartViewState.copy(configurations = it.uartViewState.configurations - configuration))
        }
    }

    fun addConfiguration(address: String, configuration: UARTConfiguration) {
        // Add the new configuration to the list
        _dataMap[address]?.update {
            val newConfig = configuration.copy(id = it.uartViewState.configurations.size + 1)
            it.copy(uartViewState = it.uartViewState.copy(configurations = it.uartViewState.configurations + newConfig))
        }
    }

    fun updateSelectedConfigurationName(address: String, configurationName: String) {
        _dataMap[address]?.update {
            it.copy(uartViewState = it.uartViewState.copy(selectedConfigurationName = configurationName))
        }
    }

    fun loadPreviousConfigurations(address: String, configuration: List<UARTConfiguration>) {
        _dataMap[address]?.update {
            it.copy(uartViewState = it.uartViewState.copy(configurations = configuration))
        }
    }

    fun removeSelectedConfiguration(address: String) {
        _dataMap[address]?.update {
            it.copy(uartViewState = it.uartViewState.copy(selectedConfigurationName = null))
        }
    }

    fun onEditConfiguration(address: String) {
        _dataMap[address]?.update {
            it.copy(uartViewState = it.uartViewState.copy(isConfigurationEdited = !it.uartViewState.isConfigurationEdited))
        }
    }

    fun onEditMacro(address: String, editPosition: Int?) {
        _dataMap[address]?.update {
            it.copy(uartViewState = it.uartViewState.copy(editedPosition = editPosition))
        }
    }

    fun addOrEditMacro(address: String, macro: UARTMacro): UARTConfiguration? {
        var newConfig: UARTConfiguration? = null
        _dataMap[address]?.update {
            it.uartViewState.selectedConfiguration?.let { selectedConfiguration ->
                val macros = selectedConfiguration.macros.toMutableList().apply {
                    set(it.uartViewState.editedPosition!!, macro)
                }
                newConfig = selectedConfiguration.copy(macros = macros)
                // Save the new configuration and edited position.
                val newConfiguration = it.uartViewState.configurations.map { config ->
                    if (config.id == selectedConfiguration.id) {
                        newConfig
                    } else {
                        config
                    }
                }
                it.copy(
                    uartViewState = it.uartViewState.copy(
                        configurations = newConfiguration,
                        editedPosition = null
                    )
                )
            }!!
        }
        return newConfig
    }

    fun onEditFinished(address: String) {
        _dataMap[address]?.update {
            it.copy(uartViewState = it.uartViewState.copy(editedPosition = null))
        }
    }

    fun onDeleteMacro(address: String) {
        _dataMap[address]?.update {
            it.uartViewState.selectedConfiguration?.let { selectedConfiguration ->
                val macros = selectedConfiguration.macros.toMutableList().apply {
                    set(it.uartViewState.editedPosition!!, null)
                }
                val newConfig = selectedConfiguration.copy(macros = macros)

                // Save the new configuration and edited position.
                val newConfiguration = it.uartViewState.configurations.map { config ->
                    if (config.id == selectedConfiguration.id) {
                        newConfig
                    } else {
                        config
                    }
                }
                it.copy(
                    uartViewState = it.uartViewState.copy(
                        configurations = newConfiguration,
                        editedPosition = null
                    )
                )
            }!!
        }
    }
}